// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <pollux/common/base/runtime_metrics.h>
#include <gtest/gtest.h>

namespace kumo::pollux {

class RuntimeMetricsTest : public testing::Test {
 protected:
  static void testMetric(
      const RuntimeMetric& rm1,
      int64_t expectedSum,
      int64_t expectedCount,
      int64_t expectedMin = std::numeric_limits<int64_t>::max(),
      int64_t expectedMax = std::numeric_limits<int64_t>::min()) {
    EXPECT_EQ(expectedSum, rm1.sum);
    EXPECT_EQ(expectedCount, rm1.count);
    EXPECT_EQ(expectedMin, rm1.min);
    EXPECT_EQ(expectedMax, rm1.max);
  }
};

TEST_F(RuntimeMetricsTest, basic) {
  RuntimeMetric rm1;
  testMetric(rm1, 0, 0);

  rm1.addValue(5);
  testMetric(rm1, 5, 1, 5, 5);

  rm1.addValue(11);
  testMetric(rm1, 16, 2, 5, 11);

  rm1.addValue(3);
  testMetric(rm1, 19, 3, 3, 11);

  ASSERT_EQ(
      fmt::format(
          "sum:{}, count:{}, min:{}, max:{}, avg: {}",
          rm1.sum,
          rm1.count,
          rm1.min,
          rm1.max,
          rm1.sum / rm1.count),
      rm1.toString());

  RuntimeMetric rm2;

  rm1.merge(rm2);
  testMetric(rm1, 19, 3, 3, 11);

  rm2.addValue(53);
  rm1.merge(rm2);
  testMetric(rm1, 72, 4, 3, 53);

  rm1.aggregate();
  testMetric(rm1, 72, 1, 72, 72);

  RuntimeMetric rm3;
  rm3.aggregate();
  testMetric(rm3, 0, 0, 0, 0);

  RuntimeMetric byteRm(RuntimeCounter::Unit::kBytes);
  byteRm.addValue(5);
  ASSERT_EQ(byteRm.toString(), "sum:5B, count:1, min:5B, max:5B, avg: 5B");

  RuntimeMetric timeRm(RuntimeCounter::Unit::kNanos);
  timeRm.addValue(2'000);
  ASSERT_EQ(
      timeRm.toString(),
      "sum:2.00us, count:1, min:2.00us, max:2.00us, avg: 2.00us");
}

} // namespace kumo::pollux
